#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
template <typename T>
class block_queue{
private:
    bool is_empty(){
        return  _block_queue.empty();
    }
     bool is_full(){
        return _block_queue.size()==_max_cap;
    }
public:
       block_queue(int max_cap)
        :_max_cap(max_cap)
        {
            pthread_mutex_init(&lock_b,nullptr);
            pthread_mutex_init(&lock_p,nullptr);
            pthread_cond_init(&cond,nullptr);
        }
        void pop(T*out){
            pthread_mutex_lock(&lock_p);
            while(this->is_empty()){
                 pthread_cond_wait(&cond,&lock_p);
            }
            *out=_block_queue.front();
            _block_queue.pop();
             pthread_mutex_unlock(&lock_p);
             pthread_cond_signal(&cond);
        }
        void push(T& in){
             pthread_mutex_lock(&lock_b);
            while(this->is_full()){
                 pthread_cond_wait(&cond,&lock_p);
            }
            _block_queue.push(in);
             pthread_mutex_unlock(&lock_b);
             pthread_cond_signal(&cond);
        }
        ~block_queue(){
            pthread_cond_destroy(&cond);
            pthread_mutex_destroy(&lock_b);
            pthread_mutex_destroy(&lock_p);
        };

private:
    int _max_cap;
    std::queue<T> _block_queue;
    pthread_cond_t   cond;
    pthread_mutex_t lock_p;
    pthread_mutex_t lock_b;
};